﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Net.Configuration;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DriveBeamEditor.Annotations;
using DriveBeamEditor.Interfaces;
using DriveBeamEditor.Tools;
using JBeamLibrary.Tools;
using JColor = JBeamLibrary.VehicleParts.Elements.Color;

namespace DriveBeamEditor.Controls.General
{
    public partial class ColorEdit : UserControl, IEditor, INotifyPropertyChanged
    {
        #region Fields

        public event EventHandler ValueChanged;
        public event EventHandler EditValueChanged;
        public event EventHandler EditableChanged;

        #endregion

        #region Properties

        public byte Alpha
        {
            get { return byte.Parse(kvcA.EditValue.ToStringOrZero()); }
            set { kvcA.EditValue = value; }
        }

        public byte Red
        {
            get { return byte.Parse(kvcR.EditValue.ToStringOrZero()); }
            set { kvcR.EditValue = value; }
        }

        public byte Green
        {
            get { return byte.Parse(kvcG.EditValue.ToStringOrZero()); }
            set { kvcG.EditValue = value; }
        }

        public byte Blue
        {
            get { return byte.Parse(kvcB.EditValue.ToStringOrZero()); }
            set { kvcB.EditValue = value; }
        }

        public JColor Color
        {
            get { return new JColor(Alpha, Red, Green, Blue); }
            set { EditValue = value; }
        }

        public object EditValue
        {
            get { return Color; }
            set
            {
                /* Reset values on null */
                if (value == null || value == System.DBNull.Value)
                {
                    Alpha = 0;
                    Red = 0;
                    Green = 0;
                    Blue = 0;
                    return;
                }

                /* Invalid type provided */
                if (!(value is JColor))
                    throw new ArgumentException(
                        string.Format("EditValue must take a Color object. Given object was of type {0}.", value.GetType().Name));

                /* Update values */
                var val = (JColor)value;
                Alpha = val.A;
                Red = val.R;
                Green = val.G;
                Blue = val.B;

                /* Notify property change */
                OnPropertyChanged();
            }
        }

        public string Value
        {
            get { return EditValue != null ? EditValue.ToString() : null; }
            set
            {
                if (Value.Equals(value)) return;
                if (string.IsNullOrEmpty(value))
                    EditValue = null;
                else
                    EditValue = JColor.Parse(value);
                OnValueChanged();
            }
        }

        public bool Editable
        {
            get { return kvcA.Editable; }
            set
            {
                kvcA.Editable = value;
                kvcR.Editable = value;
                kvcG.Editable = value;
                kvcB.Editable = value;
                OnEditableChanged();
            }
        }

        public bool ReadOnly
        {
            get { return kvcA.ReadOnly; }
            set
            {
                kvcA.ReadOnly = value;
                kvcR.ReadOnly = value;
                kvcG.ReadOnly = value;
                kvcB.ReadOnly = value;
            }
        }

        #endregion

        #region CTORs

        public ColorEdit()
        {
            InitializeComponent();
        }

        #endregion

        #region Events

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (kvcA.Editor != null && kvcA.Editor.Control is NumEdit)
                ((NumEdit) kvcA.Editor.Control).ShowButtons = false;
            if (kvcR.Editor != null && kvcR.Editor.Control is NumEdit)
                ((NumEdit)kvcR.Editor.Control).ShowButtons = false;
            if (kvcG.Editor != null && kvcG.Editor.Control is NumEdit)
                ((NumEdit)kvcG.Editor.Control).ShowButtons = false;
            if (kvcB.Editor != null && kvcB.Editor.Control is NumEdit)
                ((NumEdit)kvcB.Editor.Control).ShowButtons = false;
        }

        private void xbPick_Click(object sender, EventArgs e)
        {
            if (colorDialog.ShowDialog(this) == DialogResult.OK)
            {
                Color = UIHelper.JColorFromColor(colorDialog.Color);
            }
        }

        private void kvc_EditValueChanged(object sender, EventArgs e)
        {
            if (EditValueChanged != null)
                EditValueChanged(this, e);
        }

        #endregion

        #region Methods

        private void OnEditableChanged()
        {
            if (!Editable && Enabled) Enabled = false;

            if (EditableChanged != null)
                EditableChanged(this, new EventArgs());
        }

        private void OnValueChanged()
        {
            if (ValueChanged != null)
                ValueChanged(this, new EventArgs());
        }

        public void SetEditValueSilent(object value)
        {
            /* Reset values if null */
            if (value == null)
            {
                kvcA.SetEditValueSilent(0);
                kvcR.SetEditValueSilent(0);
                kvcG.SetEditValueSilent(0);
                kvcB.SetEditValueSilent(0);
                return;
            }

            /* Invalid value type */
            if (!(value is JColor))
                throw new ArgumentException(
                    string.Format("EditValue must take a Color object. Given object was of type {0}.", value.GetType().Name));

            /* Update editors */
            var val = (JColor)value;
            kvcA.SetEditValueSilent(val.A);
            kvcR.SetEditValueSilent(val.R);
            kvcG.SetEditValueSilent(val.G);
            kvcB.SetEditValueSilent(val.B);
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}
